package gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.bbn.openmap.MapBean;
import com.bbn.openmap.MouseDelegator;
import com.bbn.openmap.event.CenterListener;
import com.bbn.openmap.event.CenterSupport;
import com.bbn.openmap.event.MapMouseMode;
import com.bbn.openmap.event.PanListener;
import com.bbn.openmap.event.PanSupport;
import com.bbn.openmap.event.ProjectionEvent;
import com.bbn.openmap.event.ProjectionListener;
import com.bbn.openmap.event.ZoomEvent;
import com.bbn.openmap.event.ZoomListener;
import com.bbn.openmap.event.ZoomSupport;
import com.bbn.openmap.gui.CombinedCoordPanel;
import com.bbn.openmap.gui.DimensionQueryPanel;
import com.bbn.openmap.gui.LayerControlButtonPanel;
import com.bbn.openmap.gui.LayerPane;
import com.bbn.openmap.gui.LayersPanel;
import com.bbn.openmap.gui.OMToolComponent;
import com.bbn.openmap.gui.OverviewMapHandler;
import com.bbn.openmap.proj.Projection;

import languages.Language;

public class Navigation extends OMToolComponent implements ActionListener, ProjectionListener{
	
	private Window window;
	private Language language;
	private PanSupport panSupport;
	private CenterSupport centerDelegate;
	private ZoomSupport zoomDelegate;
	private Projection projection;
	
	private JButton drag;
	private JButton select;
	private JButton addNode;
	private JButton addArc;
	
	private JButton up;
	private JButton down;
	private JButton left;
	private JButton right;
	private JButton middle;
	
	private JButton plus;
	private JButton minus;
	private JTextField scale;
	private java.text.DecimalFormat df = new java.text.DecimalFormat("###,###,###");
	
	private JLabel lon; //x
	private JLabel lat; //y
	private JTextField xPos;
	private JTextField yPos;
	
	private JPanel panel;
	
	public final static String defaultKey = "navigatepanel";
	
	public Navigation(Window window, Language language) {
		super();
		
		this.window = window;
		this.language = language;
		
		panSupport = new PanSupport(this);
		centerDelegate = new CenterSupport(this);
		zoomDelegate = new ZoomSupport(this);
		
		panel = new JPanel();
		
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		panel.add(option());
		panel.add(navigation());	
		panel.add(scale());
		panel.add(position());
		panel.add(layers());
		
		add(panel);
		
	}

	private Component layers() {
JPanel panel = new JPanel();
//TODO language
		
		panel.setBorder(BorderFactory.createTitledBorder("Warstwy"));
		panel.setLayout(new GridLayout(2,1));
		
		panel.add(new JCheckBox("Pokaz wezly"));
		panel.add(new JCheckBox("Pokaz krawedzie"));
		
		return panel;
	}

	private JPanel option() {
		JPanel panel = new JPanel();
		
		panel.setBorder(BorderFactory.createTitledBorder( language.navigationMouse() ));
		panel.setLayout(new GridLayout(2,2));
		
		drag = new JButton(getButtonIcon("pan"));
//		drag.setSize(25, 25);
		drag.setActionCommand("DRAG");
		drag.addActionListener(this);
		select = new JButton(getButtonIcon("select"));
		select.setActionCommand("SELECT");
		select.addActionListener(this);
		addNode = new JButton(getButtonIcon("point"));
//		addNode.setSize(25, 25);
		addNode.setActionCommand("AN");
		addNode.addActionListener(this);
		addArc = new JButton(getButtonIcon("arc"));
		addArc.setActionCommand("AA");
		addArc.addActionListener(this);
		
		panel.add(drag);
		panel.add(select);
		panel.add(window.getDrawPoint());
		panel.add(window.getDrawPoly());
		
		return panel;
	}

//	private ImageIcon getImage(String res){
//		ImageIcon image = new ImageIcon((URL)Menu.class.getResource("../resources/icons/"+ res +".gif"));
//		
//		return image;
//	}
	
	private JPanel navigation() {
		JPanel panel = new JPanel();
		
		panel.setBorder(BorderFactory.createTitledBorder( language.navigationMove() ));
		panel.setLayout(new GridLayout(3,3));
		
		up = new JButton(getButtonIcon("top"));
		up.setSize(45, 45);
		up.setActionCommand("UP");
		up.addActionListener(this);
		down = new JButton(getButtonIcon("bot"));
		down.setActionCommand("DOWN");
		down.addActionListener(this);
		left = new JButton(getButtonIcon("left"));
		left.setActionCommand("LEFT");
		left.addActionListener(this);
		right = new JButton(getButtonIcon("right"));
		right.setActionCommand("RIGHT");
		right.addActionListener(this);
		middle = new JButton(getButtonIcon("mid"));
		middle.setActionCommand("MIDDLE");
		middle.addActionListener(this);
		
		panel.add(new JLabel());
		panel.add( up);
		panel.add(new JLabel());
		panel.add( left);
		panel.add( middle);
		panel.add( right);
		panel.add(new JLabel());
		panel.add( down);
		panel.add(new JLabel());
		
		return panel;
	}
	
	private JPanel scale() {
		JPanel panel = new JPanel();
		
		panel.setBorder(BorderFactory.createTitledBorder( language.navigationScale() ));
		panel.setLayout(new BorderLayout());
		
		plus = new JButton(getButtonIcon("+"));
		plus.setActionCommand("PLUS");
		plus.addActionListener(this);
		minus = new JButton(getButtonIcon("-"));
		minus.setActionCommand("MINUS");
		minus.addActionListener(this);
		
		scale = new JTextField("",10);
		scale.setActionCommand("SCALE");
		scale.addActionListener(this);
		
		gridbag.setConstraints(scale, c);
		
		panel.add(BorderLayout.WEST, plus);
		panel.add(BorderLayout.EAST, minus);
		panel.add(BorderLayout.CENTER, scale);
		
		return panel;
	}
	
	private JPanel position() {
		JPanel panel = new JPanel();
		
		panel.setBorder(BorderFactory.createTitledBorder( language.navigationPosition() ));
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		panel.add(new JLabel("<html><b>"+ language.navigationPositionLongtitude() +"</b></html>"));
		lon = new JLabel();
		panel.add(lon);
		
		panel.add(new JLabel("<html><b>"+ language.navigationPositionLattitude() +"</b></html>"));
		lat = new JLabel();
		panel.add(lat);
		
		panel.add(new JLabel("<html><b>"+ language.navigationPositionLonPos() +"</b></html>"));
		xPos = new JTextField(window.getMapBean().getCenter().getLongitude()+"");
		xPos.setActionCommand("XPOS");
		xPos.addActionListener(this);
		panel.add(xPos);
		
		panel.add(new JLabel("<html><b>"+ language.navigationPositionLatPos() +"</b></html>"));
		yPos = new JTextField(window.getMapBean().getCenter().getLatitude()+"");
		yPos.setActionCommand("YPOS");
		yPos.addActionListener(this);
		panel.add(yPos);
		
//		panel.add(new OverviewMapHandler());
		
		return panel;
	}
	
	private ImageIcon getButtonIcon(String iconName){
		java.net.URL imgURL = getClass().getResource("../resources/icons/"+iconName+".png");
		ImageIcon img = null;
		if (imgURL != null) 
			 img = new ImageIcon(imgURL);
		
		return img;
	}
	
	protected ImageIcon createImageIcon(String path,
		            String description) {
		java.net.URL imgURL = getClass().getResource(path);
		if (imgURL != null) {
		return new ImageIcon(imgURL, description);
		} else {
		System.err.println("Couldn't find file: " + path);
		return null;
		}
		}

	private void firePanEvent(float az) {
        panSupport.firePan(az);
    }
	
	protected void fireScaleChange(float scale2) {
		zoomDelegate.fireZoom(ZoomEvent.ABSOLUTE, scale2);
	}
	
	private void setScale(String strscale) {
		float scale2;

		int colon = strscale.indexOf(':');

		if (colon > -1) {
			strscale = strscale.substring(colon + 1);
		}

		try {
			if (strscale.toLowerCase().endsWith("m")) {
				strscale = strscale.substring(0, strscale.length() - 1);
				scale2 = df.parse(strscale).floatValue() * 1000000f;
				if (scale2 >= 1f)
					fireScaleChange(scale2);
			} else if (strscale.toLowerCase().endsWith("k")) {
				strscale = strscale.substring(0, strscale.length() - 1);
				scale2 = df.parse(strscale).floatValue() * 1000f;
				if (scale2 >= 1f)
					fireScaleChange(scale2);
			} else if (strscale.trim().equals("")) {
				return; // ignore empty string
			} else {
				scale2 = df.parse(strscale).floatValue();
				if (scale2 >= 1f)
					fireScaleChange(scale2);
			}
		} catch (java.text.ParseException e) {
			System.out.println("Parse exception: ");
		} catch (NumberFormatException e) {
			System.out.println("Number format exception");
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		System.out.println(command);
		
		if("UP".equals(command)){
			firePanEvent(0f);
		}
		else if("DOWN".equals(command)){
			firePanEvent(180f);
		}
		else if("LEFT".equals(command)){
			firePanEvent(270f);
		}
		else if("RIGHT".equals(command)){
			firePanEvent(90f);
		}
		else if("MIDDLE".equals(command)){
			window.getMapBean().setCenter(52f, 18.5f);
		}
		else if("PLUS".equals(command)){
			zoomDelegate.fireZoom(ZoomEvent.RELATIVE, 0.5f);
		}
		else if("MINUS".equals(command)){
			zoomDelegate.fireZoom(ZoomEvent.RELATIVE, 2.0f);
		}
		else if("SCALE".equals(command)){
			setScale(scale.getText());
		}
		else if("XPOS".equals(command) || "YPOS".equals(command)){
			window.getMapBean().setCenter(Float.parseFloat(yPos.getText().trim()), Float.parseFloat(xPos.getText().trim()));
//			System.out.println(Float.parseFloat(xPos.getText().trim())+" "+window.getMapBean().getCenter().getLongitude());
		}
		else if("DRAG".equals(command)){
			window.getMenu().setMouseModeById(0);
		}
		else if("SELECT".equals(command)){
			window.getMenu().setMouseModeById(1);
		}
	}

	public void findAndInit(Object obj) {
		if (obj instanceof PanListener) {
			addPanListener((PanListener) obj);
		}
		if (obj instanceof CenterListener) {
			addCenterListener((CenterListener) obj);
		}
		if (obj instanceof ZoomListener) {
            addZoomListener((ZoomListener) obj);
        }
		if (obj instanceof MapBean){
			if((MapBean)obj != null){
				addZoomListener((ZoomListener) obj);
				((MapBean) obj).addProjectionListener(this);
				scale.setText("1:" + String.valueOf(((MapBean)obj).getScale()));
			}
		}
	}

	public void findAndUndo(Object obj) {
		if (obj instanceof PanListener) {
			removePanListener((PanListener) obj);
		}
		if (obj instanceof CenterListener) {
			removeCenterListener((CenterListener) obj);
		}
		if (obj instanceof ZoomListener) {
            removeZoomListener((ZoomListener) obj);
        }
		if (obj instanceof MapBean){
			if((MapBean)obj != null){
				removeZoomListener((ZoomListener) obj);
				((MapBean)obj).removeProjectionListener(this);
				scale.setText(" ");
			}
		}
	}

	public synchronized void addCenterListener(CenterListener listener) {
		centerDelegate.addCenterListener(listener);
	}
	
	public synchronized void removeCenterListener(CenterListener listener) {
        centerDelegate.removeCenterListener(listener);
    }
	
	public synchronized void addPanListener(PanListener listener) {
		panSupport.addPanListener(listener);
    }
	
	public synchronized void removePanListener(PanListener listener) {
		panSupport.removePanListener(listener);
	}
	
	public synchronized void addZoomListener(ZoomListener listener) {
		zoomDelegate.addZoomListener(listener);
	}

	public synchronized void removeZoomListener(ZoomListener listener) {
		zoomDelegate.removeZoomListener(listener);
	}
	

	@Override
	public void projectionChanged(ProjectionEvent e) {
		Projection newProj = e.getProjection();
        if (projection == null || (!projection.equals(newProj))) {
            setProjection((Projection) newProj.makeClone());
        }
	}
	
	public synchronized void setProjection(Projection aProjection) {
        projection = aProjection;

        String oldScale = scale.getText();
        String newScale = df.format(projection.getScale());

        if (!oldScale.equals(newScale)) {
            scale.setText("1:" + newScale);
        }
    }
}
